package com.smec.moblie.util.imageuploader;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.util.Log;

import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.RequestParams;
import com.smec.moblie.activity.MainDetailActivity;
import com.smec.moblie.common.ConstValue;
import com.smec.moblie.control.EventCenter;
import com.smec.moblie.util.ConfigContext;

import org.apache.http.Header;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import de.greenrobot.event.EventBus;

/**
 * Created by snipking on 14-2-25.
 */
public class ResourceFacade implements ConstValue{

    private int uploadIndicator;
    private static final String SERVICE_PATH = "rest/resources";
    private boolean isfailed = false;

    Context context;

    public ResourceFacade(Context context) {
        this.context = context;
    }

    public void uploadFiles(List<FndResource> resources,
                            ResourceResponseHandler resultHandler) {
        UploadList uploadList = UploadList.getInstance(context);
        uploadList.bulkAddToUploadList(resources);
        this.startUploadFiles(resultHandler);
    }


    /**
     * 传输照片
     *
     * @param resources
     */
    public void startUploadFilesNew(List<FndResource> resources) throws Exception {
        this.setUploadIndicator(resources.size());

        for (final FndResource resource : resources) {
            File file = new File(Environment.getExternalStorageDirectory() + "/DCIM/Camera/" +
                    resource.getResourceId() + ".jpeg");
            if (file.exists()) {

                Log.i("uploadimg", "imgeuploading");
                AsyncHttpClient client = new AsyncHttpClient();
                try {
                    // prepare upload param
                    InputStream fileInputStream = ResourceFacade
                            .loadResourceFromLocalCache(resource.getResourceId());
//				Log.i("uploadimg", "~~fileInputStream size:"+fileInputStream.available());
                    RequestParams params = new RequestParams();
                    params.put(resource.getResourceId(), fileInputStream,
                            resource.getFileName(), resource.getContentType());
                    // do post request
                    client.setTimeout(20 * 1000);//20秒超时
                    client.post(SERVER_BASE_PATH + SERVICE_PATH,
                            params, new AsyncHttpResponseHandler() {
                                @Override
                                public void onSuccess(String response) {
                                    Log.d(ResourceFacade.class.getSimpleName(),
                                            "~~File " + resource.getResourceId()
                                                    + " upload success.");


                                    EventBus.getDefault().post(new EventCenter.SingleImageUploadSuccess(resource));
                                    ResourceFacade.this.decreaseUploadIndicator();
                                    // decide upload finish
                                    if (ResourceFacade.this.getUploadIndicator() == 0 && !isfailed) {
                                        EventBus.getDefault().post(new EventCenter.AllImageUploadSuccess());
                                    }
                                }

                                @Override
                                public void onFailure(int statusCode,
                                                      Header[] headers, byte[] responseBody,
                                                      Throwable error) {
                                    super.onFailure(statusCode, headers,
                                            responseBody, error);
                                    Log.e(MainDetailActivity.class.getSimpleName(),
                                            "~~File upload failed statusCode: "
                                                    + statusCode + ", headers: "
                                                    + headers + ", responseBody: "
                                                    + responseBody, error);
                                    if(!isfailed) {
                                        EventBus.getDefault().post(new EventCenter.UploadImageFailed());
                                    }
                                    // decide upload finish
                                    ResourceFacade.this.decreaseUploadIndicator();
                                    isfailed = true;
                                }
                            });
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                    Log.e(this.getClass().getSimpleName(), "resource not found ",
                            e.getCause());
                    EventBus.getDefault().post(new EventCenter.UploadImageFailed());
                }
            }
        }
    }


    public void startUploadFiles(final ResourceResponseHandler resultHandler) {
        final UploadList uploadList = UploadList.getInstance(context);
        List<FndResource> resources = uploadList.getToUploadList();
        final List<FndResource> failedList = new ArrayList<FndResource>();
        this.setUploadIndicator(resources.size());
        for (final FndResource resource : resources) {
//			Log.i("uploadimg", "~~imgeuploading");
            AsyncHttpClient client = new AsyncHttpClient();
            try {
                // prepare upload param
                InputStream fileInputStream = ResourceFacade
                        .loadResourceFromLocalCache(resource.getResourceId());
                RequestParams params = new RequestParams();
                params.put(resource.getResourceId(), fileInputStream,
                        resource.getFileName(), resource.getContentType());
                // do post request
                client.post(SERVER_BASE_PATH + SERVICE_PATH,
                        params, new AsyncHttpResponseHandler() {
                            @Override
                            public void onSuccess(String response) {
                                Log.d(ResourceFacade.class.getSimpleName(),
                                        "~~File " + resource.getResourceId()
                                                + " upload success.");
                                uploadList.removeFromUploadList(resource
                                        .getResourceId());

                                resultHandler.onItemUploadSuccess(resource);

                                // decide upload finish
                                ResourceFacade.this.decreaseUploadIndicator();
                                if (ResourceFacade.this.getUploadIndicator() == 0) {
                                    resultHandler.onFinish(failedList);
                                }
                            }

                            @Override
                            public void onFailure(int statusCode,
                                                  Header[] headers, byte[] responseBody,
                                                  Throwable error) {
                                super.onFailure(statusCode, headers,
                                        responseBody, error);
                                Log.e(MainDetailActivity.class.getSimpleName(),
                                        "~~File upload failed statusCode: "
                                                + statusCode + ", headers: "
                                                + headers + ", responseBody: "
                                                + responseBody, error);
                                resultHandler.onItemUploadFailure(resource,
                                        statusCode, error);

                                // add failed resource to failed list
                                failedList.add(resource);

                                // decide upload finish
                                ResourceFacade.this.decreaseUploadIndicator();
                                if (ResourceFacade.this.getUploadIndicator() == 0) {
                                    resultHandler.onFinish(failedList);
                                }
                            }
                        });
            } catch (FileNotFoundException e) {
                resultHandler.onItemUploadFailure(resource, 0, e.getCause());
                e.printStackTrace();
                Log.e(this.getClass().getSimpleName(), "resource not found ",
                        e.getCause());
            }
        }
    }

    private void setUploadIndicator(int value) {
        uploadIndicator = value;
    }

    private void decreaseUploadIndicator() {
        synchronized (ResourceFacade.class) {
            uploadIndicator--;
        }
    }

    private int getUploadIndicator() {
        synchronized (ResourceFacade.class) {
            return uploadIndicator;
        }
    }

    public static InputStream loadResourceFromLocalCache(String resourceId)
            throws FileNotFoundException {
        File file = new File(Environment.getExternalStorageDirectory() + "/DCIM/Camera/" +
                resourceId + ".jpeg");
        Log.d(ResourceFacade.class.getSimpleName(),
                "load resource from local cache with real file path: "
                        + file.getAbsolutePath());
        if (!file.exists()) {
            throw new FileNotFoundException();
        }
        return new FileInputStream(file);
    }

    public static boolean saveResourceToLocalCache(InputStream is,
                                                   String resourceId) throws IOException {
        File file = new File(ConfigContext.getInstance().getImgPath() +
                resourceId + ".jpeg");
        byte[] buffer = new byte[1024];
        int readCount = 0;
        if (!file.exists()) {
            file.createNewFile();
        }
        FileOutputStream fos = new FileOutputStream(file);
        while ((readCount = is.read(buffer)) != -1) {
            fos.write(buffer, 0, readCount);
        }
        is.close();
        fos.flush();
        fos.close();
        return true;
    }

    public static Bitmap loadImageFromLocalCache(String resourceId) {
        try {
            InputStream is = ResourceFacade
                    .loadResourceFromLocalCache(resourceId);
            if (is != null) {
                Bitmap bitmap = BitmapFactory.decodeStream(is);
                is.close();
                return bitmap;
            } else {
                return null;
            }
        } catch (FileNotFoundException e) {
            Log.e(ResourceFacade.class.getSimpleName(),
                    "Load image from local cache failed. ", e);
            e.printStackTrace();
        } catch (IOException e) {
            Log.e(ResourceFacade.class.getSimpleName(),
                    "Load image from local cache failed. ", e);
            e.printStackTrace();
        }
        return null;
    }

    public static boolean saveImageToLocalCache(Bitmap bitmap, String resourceId) {
        boolean result = false;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        bitmap.compress(CompressFormat.JPEG, 100, bos);
        byte[] bitmapdata = bos.toByteArray();
        ByteArrayInputStream bs = new ByteArrayInputStream(bitmapdata);
        try {
            ResourceFacade.saveResourceToLocalCache(bs, resourceId);
            result = true;
        } catch (IOException e) {
            Log.e(ResourceFacade.class.getSimpleName(),
                    "Load image from local cache failed. ", e);
            e.printStackTrace();
        }
        return result;
    }
}
